#include <assemble.h>
#include <string.h>
#include <display.h>
#include <sys_call.h>
#include "process.h"

void init_interupt(void);
void init_proc(void);
void init_clock(void);
void init_tty();
void init_disk();
void init_mm();
void init_cache();
void init_fs();

void idle()
{
	while(1) {
		sys_alarm(0);
	}
}

static void split_args(char *arg_line, char **argv)
{
	int i = 0, flag = 1;
	int argc = 0;
	while (1) {
		if (arg_line[i] == '\0') {
			break;
		} else if (arg_line[i] == ' ') {
			arg_line[i] = '\0';
			flag = 1;
		} else if (flag == 1) {
			argv[argc++] = &arg_line[i];
			flag = 0;
		}
		i++;
	}
	argv[argc] = NULL;
}
static int test_ls(int argc, char *argv[])
{
	int n, r, file, len;
	char fname[100], path[100];
	struct inode stat;
	int showall = 1;

	strcpy(path, (argc==1 ? "/" : argv[1]));
	n = sys_opendir(path);
	if(n < 0) {
		printf("error in open dir: %d\n", n);
		return -1;
	}

	len = strlen(path);
	if(path[len - 1] != '/')
		path[len++] = '/';

	while(1) {
		r = sys_readdir(n, fname);
		if (r == -1)
			printf("Wrong!\n");
		if (r == 0)
			break;

		if(showall == 0 && fname[0] == '.')
			continue;

		strcpy(path + len, fname);
		file = sys_open(path, 0);
		sys_stat(file, &stat);
		printf("%d  %d  %s\n", stat.size, stat.type, path);
		sys_close(file);
	}
	sys_exit(0);
	return 0;
}
static int test_flust(int argc, char *argv[])
{
	sys_flush();
	sys_exit(0);
	return 0;
}
static int test_format(int argc, char *argv[])
{
	sys_format();
	sys_exit(0);
	return 0;
}
static int test_null(int argc, char *argv[])
{
	printf("null\n");
	sys_exit(0);
	return 0;
}

static int pseud_shell(void)
{
	char cmd[20];
	int ret, i;
	int pid;
	char *argv[10];
	struct {char name[10]; int (*func)(); } commands[] = {
		{"format", test_format},
		{"flush", test_flust},
		{"read", test_null},
		{"write", test_null},
		{"ls", test_ls},
		{"mkdir", test_null},
		{"rmdir", test_null},
		{"rm", test_null}};

	while(1) {
		printf("pigos> ");
		sys_read_tty(cmd);

		/* Only Enter. */
		if (cmd[0] == '\0')
			continue;

		/* Split the arguments. */
		split_args(cmd, argv);

		for(i = 0; i < sizeof(commands) / sizeof(commands[0]); i++) {
			if(strcmp(cmd, commands[i].name) == 0)
				break;
		}
		pid = sys_fork();
		if(pid == 0) {
			if(i == sizeof(commands) / sizeof(commands[0]))
				ret = sys_exec(cmd, argv);
			else
				ret = sys_exec1(commands[i].func, argv);
			if(ret != 0)
				printf("error in exec! %d\n", ret);
		}
		sys_wait(0);
	}
}

void first()
{
	int pid;
	char *argv = 0;

	pid = sys_fork();
	if(pid == 0) {
		sys_exec1(pseud_shell, &argv);
	}
	idle();
}

void init()
{
/* Here, in kernel level, no hardware interupts, and without
 * process schedular.
 */
	init_interupt();
	init_proc();
	init_clock();
	init_tty();
	init_mm();
	init_disk();
	init_cache();
	sti_a();
	init_fs();
	init_shm();

	first_proc(first);
}
